home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 07 - 1991 / 07.08 Aug 91 / Dots Source / cDotsPane.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-04  |  7.3 KB  |  303 lines  |  [TEXT/KAHL]

  1. /**************************************
  2.     cDotsPane.c
  3.  
  4.     SUPERCLASS = CPanorama
  5.  
  6. Methods for the dots pane. The dots pane contains the grid where the
  7. game is actually played. Line segments are selected by clicking on the area
  8. between two horizontal or two vertical dots. When the four line segments
  9. surrounding a grid cell are selected, the pattern associated with the 
  10. player completing the 'box' is placed inside the cell.
  11.  
  12. ****************************************/
  13.  
  14. #include <CScrollPane.h>
  15. #include "cDotsDoc.h"
  16. #include "cDotsPane.h"
  17. #include "cDotsTask.h"
  18. #include "dotsTypes.h"
  19.  
  20. /*** Class Constants ***/
  21. #define kHalfDotSize    3
  22. #define kFullDotSize    (2*kHalfDotSize+1)
  23. #define kHalfLineSize    1
  24. #define kFullLineSize    (2*kHalfLineSize+1)
  25. #define kLineOffset        ((kFullDotSize - kFullLineSize) / 2)
  26. #define kDotSpacing        (4*kFullDotSize)
  27. #define UNDOMoveIndex    1    /* String index for undo */
  28.  
  29. /*** Globals ***/
  30. extern Pattern *dgPlayerPats;
  31.  
  32. /******* C O N S T R U C T I O N *******/
  33.  
  34. /*** IDotsPane {OVERRIDE}
  35. *
  36. * Initialize instance variables
  37. */
  38. void cDotsPane::IDotsPane(CView *anEnclosure, CBureaucrat *aSupervisor,
  39.                             short aWidth, short aHeight,
  40.                             short aHEncl, short aVEncl,
  41.                             SizingOption aHSizing, SizingOption aVSizing)
  42. {
  43.         /* Call the inherited method */
  44.     IPanorama(anEnclosure, aSupervisor, aWidth, aHeight,
  45.                             aHEncl, aVEncl, aHSizing, aVSizing);
  46.         /* Set horiz and vert scales so that scrolling is by dot spacing
  47.         ** rather than 1 pixel at a time */
  48.     SetScales(kDotSpacing, kDotSpacing);
  49.     SetWantsClicks(true);    /* Lines are selected by mouse clicks */
  50. }
  51.  
  52. /******** D R A W I N G **********/
  53.  
  54. /*** Draw {OVERRIDE}
  55. *
  56. * The area parameter gives the portion of the 
  57. * pane that needs to be redrawn. Area is in frame coordinates.
  58. */
  59. void cDotsPane::Draw(Rect *area)
  60. {
  61.     int    row, col;
  62.  
  63.         /* Draw entire matrix. Could be more selective and
  64.         ** base draw on input area */
  65.     for (row = 0; row <= kMaxRow; row++)
  66.         for (col = 0; col <= kMaxCol; col++)
  67.             drawCorner(row, col);
  68. }
  69.  
  70.  
  71. /*** drawCorner
  72. *
  73. * Draws the grid dots, grid lines and fills in player boxes
  74. */    
  75. void cDotsPane::drawCorner(int row, int col)
  76. {
  77.     Rect        r;
  78.     tBoxState    boxState;
  79.     
  80.     if ((row < kMaxRow) && (col < kMaxCol)) {
  81.         PenNormal();
  82.         box2Rect(row, col, &r);    /* Get box rectangle */
  83.         
  84.             /* first draw the box if it needs to be shaded in */
  85.         boxState = ((cDotsDoc *)itsSupervisor)->getBoxState(row, col);
  86.         if (boxState == kBoxPlayer1) {
  87.             FillRect(&r, &dgPlayerPats[kPlayer1]);
  88.             FrameRect(&r);
  89.         }
  90.         else if (boxState == kBoxPlayer2) {
  91.             FillRect(&r, &dgPlayerPats[kPlayer2]);
  92.             FrameRect(&r);
  93.         }
  94.     }
  95.         
  96.     dot2Rect(row, col, &r);    /* Get dot rectangle */
  97.     
  98.     PenNormal();
  99.     PenSize(kFullLineSize, kFullLineSize);
  100.     
  101.         /* Draw the line down from the dot (if any) */
  102.     if ((row < kMaxRow) &&
  103.         (((cDotsDoc *)itsSupervisor)->getLineState(vLine, row, col))) {
  104.         MoveTo(r.left+kLineOffset, r.top+kLineOffset);
  105.         Line(0, kDotSpacing);
  106.     }
  107.             
  108.         /* Draw the line right from the dot (if any) */
  109.     if ((col < kMaxCol) &&
  110.         (((cDotsDoc *)itsSupervisor)->getLineState(hLine, row, col))) {
  111.         MoveTo(r.left+kLineOffset, r.top+kLineOffset);
  112.         Line(kDotSpacing, 0);
  113.     }
  114.  
  115.     FillOval(&r, black);    /* Draw the dot */
  116. }
  117.  
  118.  
  119. /*** box2Rect
  120. *
  121. * Returns the rectangle defining the box
  122. */
  123. void cDotsPane::box2Rect(int row, int col, Rect *r)
  124. {
  125.     Point    center;
  126.     
  127.     dotCenter(row, col, ¢er);
  128.     SetRect(r, 0, 0, kDotSpacing+1, kDotSpacing+1);
  129.     OffsetRect(r, center.h, center.v);
  130.     InsetRect(r, kHalfLineSize+4, kHalfLineSize+4);
  131. }
  132.  
  133.  
  134. /*** dot2Rect
  135. *
  136. * Returns the rectangle defining a dot
  137. */
  138. void cDotsPane::dot2Rect(int row, int col, Rect *r)
  139. {
  140.     Point    center;
  141.     
  142.     dotCenter(row, col, ¢er);
  143.     SetRect(r, -kHalfDotSize, -kHalfDotSize, kHalfDotSize+1, kHalfDotSize+1);
  144.     OffsetRect(r, center.h, center.v);
  145. }
  146.  
  147.  
  148. /*** dotCenter
  149. *
  150. * Returns center coord of a given dot
  151. */
  152. void cDotsPane::dotCenter(int row, int col, Point *center)
  153. {
  154.     SetPt(center, kDotSpacing*(col+1), kDotSpacing*(row+1));
  155. }
  156.  
  157. /*** line2Pt
  158. *
  159. * Converts coord of line to a pt on grid
  160. */
  161. void cDotsPane::line2Pt(tLineDir direction, int row, int col, Point *pt)
  162. {
  163.         /* Set pt to center of dot */
  164.     dotCenter(row, col, pt);
  165.         /* Offset it to be on the requested line */
  166.     if (direction == hLine)
  167.         pt->h = pt->h + kHalfDotSize + 1;
  168.     else
  169.         pt->v = pt->v + kHalfDotSize + 1;
  170. }
  171.  
  172.  
  173. /*** line2Rect
  174. *
  175. * Convert coordinates of a line to a rectangle. Used for highlighting
  176. * while tracking and for invalidating when line is chosen
  177. */    
  178. void cDotsPane::line2Rect(tLineDir direction, int row, int col, Rect *r)
  179. {
  180.     Point    center;
  181.     
  182.         /* Set pt to center of dot */
  183.     dotCenter(row, col, ¢er);
  184.         /* Offset it to be on the requested line */
  185.     if (direction == hLine)
  186.         SetRect(r, 0, -kHalfLineSize, kDotSpacing+1, kHalfLineSize+1);
  187.     else
  188.         SetRect(r, -kHalfLineSize, 0, kHalfLineSize+1, kDotSpacing+1);
  189.     OffsetRect(r, center.h, center.v);
  190. }
  191.  
  192.  
  193. /*** pt2Line
  194. *
  195. * Convert point in grid to the coordinates of a line
  196. */
  197. Boolean cDotsPane::pt2Line(Point pt, tLineDir *direction, int *row, int *col)
  198. {
  199.     Boolean    ok;
  200.     int        modH;
  201.     int        modV;
  202.     
  203.     ok = FALSE;
  204.     
  205.         /* Offset pt by slop allowed before line */
  206.     pt.h = pt.h + kFullDotSize;
  207.     pt.v = pt.v + kFullDotSize;
  208.     
  209.         /* Determine values of row and col */
  210.     *row = pt.v / kDotSpacing - 1;
  211.     *col = pt.h / kDotSpacing - 1;
  212.  
  213.         /* Check to see if point selected is on the grid */
  214.     ok = (*row >= 0) && (*row <= kMaxRow) &&
  215.         (*col >= 0) && (*col <= kMaxCol);
  216.     if (ok) {
  217.             /* Consider taking pt.v % kDotSpacing. In order to
  218.             ** be on a horizontal line, this must be in the
  219.             ** range 0..2*kFullDotSize */
  220.         modH = pt.h % kDotSpacing;
  221.         modV = pt.v % kDotSpacing;
  222.         
  223.             /* Pick the closest line to the point */
  224.         if (modH < modV) {
  225.             *direction = vLine;
  226.             ok = (*row < kMaxRow) && (modH <= 2*kFullDotSize);
  227.         } else {
  228.             *direction = hLine;
  229.             ok = (*col < kMaxCol) && (modV <= 2*kFullDotSize);
  230.         }
  231.     }
  232.     if (!ok)
  233.         *row = *col = -1;
  234.     return(ok);
  235. }
  236.  
  237.  
  238. /*** invalLine
  239. *
  240. * Invalidate line so that it will redraw on update
  241. */
  242. void cDotsPane::invalLine(tLineDir direction, int row, int col)
  243. {
  244.     Rect    r;
  245.     
  246.     line2Rect(direction, row, col, &r);    /* Get line's rectangle */
  247.     
  248.         /* Set to dots pane's port before invalidation 
  249.         ** otherwise may be drawing in a different port */
  250.     Prepare();
  251.     InvalRect(&r);
  252. }
  253.  
  254.  
  255. /*** invalBox
  256. *
  257. * Invalidate box so that it will redraw on update
  258. */
  259. void cDotsPane::invalBox(int row, int col)
  260. {
  261.     Rect    r;
  262.     
  263.     box2Rect(row, col, &r);    /* Get box's rectangle */
  264.     
  265.         /* Set to dots pane's port before invalidation 
  266.         ** otherwise may be drawing in a different port */
  267.     Prepare();
  268.     InvalRect(&r);
  269. }
  270.  
  271. /******** M O U S E    T R A C K I N G *********/
  272.  
  273. /*** DoClick {OVERRIDE}
  274. *
  275. * Respond to a mouse down in the dots pane
  276. */ 
  277. void cDotsPane::DoClick(Point hitPt, short modifierKeys, long when)
  278. {
  279.     Rect        bounds;
  280.     cDotsTask    *theDotsTask;
  281.     short        theHScale;
  282.     short        theVScale;
  283.  
  284.         /* Set up a task both for tracking the mouse and for do/undo */
  285.     theDotsTask = new(cDotsTask);
  286.     theDotsTask->IDotsTask(UNDOMoveIndex, this, (cDotsDoc *)itsSupervisor);
  287.     
  288.         /* Set up a pin rect for autoScroll based on panorama bounds */
  289.     GetScales(&theHScale, &theVScale);
  290.     GetBounds(&bounds);
  291.     bounds.top *= theVScale;
  292.     bounds.left *= theHScale;
  293.     bounds.bottom *= theVScale;
  294.     bounds.right *= theHScale;
  295.     
  296.     TrackMouse(theDotsTask, hitPt, &bounds);
  297.  
  298.         /* Only save for undo if a valid move was made */
  299.     if (theDotsTask->validMove())
  300.         itsSupervisor->Notify(theDotsTask);  /* Let doc save for undo */
  301.     else
  302.         theDotsTask->Dispose();
  303. }